package cn.icanci.template;

import cn.icanci.template.handler.IResultSetHandler;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.List;
import java.util.Properties;

/**
 * @Author: icanci
 * @ProjectName: kangaroo-orm
 * @PackageName: cn.icanci.template
 * @Date: Created in 2020/8/31 15:07
 * @ClassAction: JdbcTemplate 用来操作数据库的
 */
public class JdbcTemplate<T> {

    /**
     * 查询语句
     *
     * @param sql 需要执行的SQL语句
     * @return 如果不为空，则返回T类型的数据
     */
    public static <T> T query(String sql, IResultSetHandler<T> rsh, Object... objects) {
        Connection conn = JdbcUtil.getConnection();
        assert conn != null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        List<T> ts = null;
        try {
            preparedStatement = conn.prepareStatement(sql);
            for (int i = 0; i < objects.length; i++) {
                // 匹配到 like
                if (sql.contains("like") && i == 0) {
                    Object s = "%" + objects[i] + "%";
                    System.out.println(s.toString());
                    preparedStatement.setObject(i + 1, s);
                } else {
                    preparedStatement.setObject(i + 1, objects[i]);
                }
            }
            resultSet = preparedStatement.executeQuery();
            return rsh.handler(resultSet);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JdbcUtil.close(conn, preparedStatement, resultSet);
        }
        throw new RuntimeException("查询有异常");
    }

    /**
     * 更新操作。包括 insert/update/delete
     *
     * @param sql     需要查询的SQL语句
     * @param objects 需要执行的参数
     * @return 返回影响的行数
     */
    public static int update(String sql, Object... objects) {
        Connection conn = JdbcUtil.getConnection();
        PreparedStatement preparedStatement = null;
        try {
            assert conn != null;
            preparedStatement = conn.prepareStatement(sql);
            for (int i = 0; i < objects.length; i++) {
                preparedStatement.setObject(i + 1, objects[i]);
            }
            return preparedStatement.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            JdbcUtil.close(conn, preparedStatement, null);
        }
        return 0;
    }

    /**
     * 操作Jdbc连接的工具类
     */
    private static class JdbcUtil {
        private static String URL = null;
        private static String USERNAME = null;
        private static String PASSWORD = null;

        private JdbcUtil() {

        }

        static {
            try {
                Properties props = new Properties();
                InputStream in = JdbcUtil.class
                        .getClassLoader()
                        .getResourceAsStream("cn/icanci/template/resources/db.properties");
                props.load(in);
                URL = props.getProperty("url");
                USERNAME = props.getProperty("username");
                PASSWORD = props.getProperty("password");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        /**
         * 或许数据库连接
         *
         * @return 返回数据库连接
         */
        public static Connection getConnection() {
            try {
                return DriverManager.getConnection(URL, USERNAME, PASSWORD);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            return null;
        }

        /**
         * 关闭资源
         *
         * @param conn 数据库连接
         * @param ps   预编译对象
         * @param rs   结果集
         */
        public static void close(Connection conn, PreparedStatement ps, ResultSet rs) {
            if (null != rs) {
                try {
                    rs.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (null != ps) {
                try {
                    ps.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (null != conn) {
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    }
}
